Audio streaming support in an operating system (OS) relies on periodic supply of audio data from or to a client application by an audio engine. A typical audio engine is responsible for reading and writing audio data, performing certain types of digital signal processing (DSP) on the data and sometimes mixing the streams of multiple clients together into one stream to be supplied (e.g., via I/O or memory writes) to audio hardware for rendering to human audible components (headphones, speakers, etc.). Audio engines also participate in capturing data (e.g. from microphones) and supplying that data to one or more applications.
Human hearing is very sensitive and timely delivery and processing of data is critical for a smooth auditory experience. Lateness in delivering data and/or delivery of incomplete data can lead to dissonant auditory effects, often known as “glitching”. Client applications that are rendering or capturing audio data must supply or read data in a timely manner. This requires a region of memory that is accessible to both the client and the OS audio engine. It is well known in the practice of software engineering that discrete components that must simultaneously access a shared memory region often require synchronization via various mechanisms, one of which is generally known as a mutex or lock. In a system that relies on a mutex or lock, one entity takes the mutex or lock and “owns” the memory region until the mutex or lock is released. All other entities must wait until the current owner releases the mutex or lock. If every entity releases the lock within a small percentage of a processing window (e.g., commonly known as the “audio engine period” or simply “period”), smooth audio will result without any audible glitches. However, in a lock-based system, any entity which holds the lock for too long (a significant percentage of the period or longer), will cause audio to completely halt, because the audio engine will be waiting for a lock to be released. In the worst case, an errant client can cause audio to cease indefinitely until the client application is terminated or is otherwise convinced to release the lock.
There are two major types of audio glitches. The first type is known as “client starvation”. This occurs when the client does not supply sufficient audio data in a timely manner. The second type is known as “audio engine starvation” and occurs when the audio engine does not supply sufficient data to a computer system's audio hardware in a timely manner. Clients who hold locks for too long in a lock-based system can cause audio engine starvation. In terms of system resiliency, it is important that clients not be able to interrupt the timely flow of audio data in the OS audio engine. Further, in a capture scenario, a client can “under read” data and lose some of the captured audio information.
Various exemplary techniques described herein can alleviate use of such aforementioned locks. An exemplary lock-free system uses one or more techniques to ensure that each individual client application (i) supplies sufficient data in a timely manner to a client's shared audio buffer when rendering or (ii) reads sufficient data in a timely manner from the client's shared audio buffer when capturing. In various lock-free examples, audio engine processing is not interrupted even if a client fails to write or read data in a timely manner. In other words, while such failure may result in a client starvation glitch for the involved stream, interruption of audio engine processing audio engine is avoided.